#include "net.h"

//线程处理客户端请求
void cli_data_handle(void* arg)
{
	/* 线程属性分离*/
	pthread_detach(pthread_self());
	
	int newfd = *(int* ) arg;
	printf("handle thread: newfd = %d\n", newfd);

	/* 读写 */
	int ret = -1;
	char buf[BUFSI];
	while(1)
	{
		bzero(buf, BUFSI);
		do
		{
			ret = read(newfd, buf, BUFSI-1);
		}while(ret < 0 && errno == EINTR);  //遇到中断重复读

		if(ret < 0)
		{
			perror("read");
			exit(0);
		}
		if(!ret)
		{
			printf("客户端以退出\n");
			break;
		}
		printf("read:%s\n", buf);

		/* 判断对方是否想退出 */
		if(!strncasecmp(buf, QUIT, strlen(QUIT)))
		{
			printf("客户端请求退出\n");
			break;
		}

		close(newfd);
	}

}


void format(char* s)
{
	printf("\n%s ser_ip ser_port", s);
	printf("\n\t ser_ip: server ip address");
	printf("\n\t ser_port: server port > 5000");

}

int main(int argc, char** argv)
{
	short port;
	int fd = -1;
	pthread_t tid;
	struct sockaddr_in soc;

	if(argc != 3)
	{

		format(argv[0]);
		exit(1);
	}

	port = atoi(argv[1]);
	if(port < 5000)
	{
		format(argv[0]);
		exit(1);
	}

	/* 创建套接字 */
	if( (fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
	{
		perror("socket");
		exit(1);
	}

	/* 设置网络属性 setsockopt */
	int b_euse = 1;
	setsockopt(fd, SOL_SOCKET,SO_REUSEADDR, &b_euse, sizeof(int));


	/* 绑定 */
	//1. 填充网络结体
	soc.sin_family = AF_INET;
	soc.sin_port = htons(port);

#if 0
	/* 任何ip都可邦定 */
	soc.sin_addr.s_addr = htonl(INADDR_ANY);
#else

	if((inet_pton(AF_INET, argv[1], (void* )&soc.sin_addr)) != 1 )
	{
		perror("inet_pton");
		exit(1);
	}
#endif
	//2.进行绑定
	if( (bind(fd, (struct sockaddr* )&soc, sizeof(soc))) < 0)
	{
		perror("bind");
		exit(1);
	}

	/* 把主动变被动 */
	if( (listen(fd, BACKLOG)) < 0)
	{
		perror("listen");
		exit(0);
	}
	printf("服务器启动成功\n");

	/* 阻塞，等待客户端连接 */
	int newfd = -1;
	/* 来获取到连接客户端的ip和端口信息 */
	struct sockaddr_in sin;
	socklen_t addrlen = sizeof(sin);
	while(1)
	{
		if( (newfd = accept(fd, (struct sockaddr* )&sin, &addrlen)) < 0)
		{
			perror("accpet");
			exit(1);
		}

		/* 打印获取到的ip和端口信息 */
		char addr[16];
		if(( !inet_ntop(AF_INET, &sin.sin_addr, addr, sizeof(sin))))
 		{
			perror("inet_pton");
			exit(1);
		}
		printf("Clinet(%s:%d)", addr, htons(sin.sin_port) );

		/* 创建线程,处理其他客户端请求 */
		pthread_create(&tid, NULL, (void *) cli_data_handle, (void *) &newfd);

	}

	close(fd);
	return 0;
}


